home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr48
/
ned100.zip
/
NEWEDIT.DOC
< prev
next >
Wrap
Text File
|
1993-04-08
|
44KB
|
1,104 lines
INTRODUCTION
------------
I originally started this project to add a wordwrap feature to
the Turbo Vision EDITORS unit. To make matters worse, I'm new
to Pascal, and trying to learn the language, Turbo
Vision, and event driven programming was just a bit of a
hurdle. So I asked for help, LOTS of help, and the next thing
I knew I was working with people I've never met trying to
create a full-blown IDE compatible wordprocessor, with the
wordwrap!
Well, it got done, minus the IDE select text features such as
read/write/indent blocks, etc. If nothing else, it was one way
of learning three things at once. We all had a lot of fun,
probably at my expense <grin>.
NEWEDIT.PAS is a complete replacement for the original EDITORS
unit. It's major contribution is the implementation of a
wordwrap feature. It also has several other features, which
will be outlined below.
If you decide to use the NEWEDIT unit with your applications,
be sure you change your use clause from "uses Editors" to "uses
NewEdit" in all code modules that require the editor. Those
modules included in the NED100.ZIP file already do this.
You should NOT overwrite your original EDITORS.PAS file! Keep
it for reference should you decide to dig into the work I have
done and add your own features. Comparison is a learning tool!
The rest of this document deals with the modifications I have
made, discussing how they work, and whatever quirks you should
be familiar with. A command summary is also provided of all
the NEWEDIT options. Last of all, a brief discussion is given
that explains how to implement your own customized key
commands.
Please note that this document is NOT written for users. It is
written for you, the programmer. A lot of the information
contained herein would severely confuse your users due to its
technical nature. Don't make life harder on them by cutting
and pasting the current text to make a quick users guide. Take
the time and effort to write your own, and make it as simple as
possible.
HOW TO USE IT
-------------
I figured I'd put this right up front so you can jump right into it.
You can use the program either as is, or you can yank out NEWEDIT and
simply patch it into your application. I'll discuss both methods.
Using NEDEMO
------------
Your best bet is to create a directory and dump all the NED100.ZIP files
into it. Baring that, put the files wherever you want.
Next, ensure that all the units called in NEDEMO.PAS are available for
compilation. Now, compile the NEDEMO.PAS source. All the other units
will compile. If you get an error message stating that a unit can't be
compiled, fix your Options|Directories so the path to the unit is
correct. Or, take the unit TPU or PAS file and put it in your
compilation directory.
Plug Into Your Application
--------------------------
The NEWEDIT unit is plug-in compatible with the standard EDITORS unit.
If you're not interested in the NEDEMO program, but want to use the
NEWEDIT unit as is, you can easily patch it into your application.
You will need the EDITPKG.PAS and NEWEDIT.PAS programs. NEWEDIT.PAS is
the actual editor. EDITPKG.PAS contains all the dialogs and calls to
the clipboard and editor.
1) In your main application INIT constructor, insert this line BEFORE
you use "TApplication.Init":
EditPkg.Initialize_The_Editor;
Then load any previous desktop and disable any editor commands you
don't want the user to have immediate access to.
Last of all, initialize the clipboard with this code:
EditPkg.Initialize_The_Clipboard;
Look at the T_EditDemo.Init code in NEDEMO.PAS if you have
questions.
2) In your main application HandleEvent code, insert this line for
opening new files:
cmNew : EditPkg.Open_Editor ('', True);
3) In your main application HandleEvent code, insert this line for
opening existing disk files:
cmOpen : EditPkg.Run_The_Editor;
4) If you write the desktop to disk, for any reason, be sure you
deallocate and reallocate the clipboard. Failure to do so will
cause your desktop file to start growing and growing! Insert this
code around your save desktop code:
EditPkg.Deallocate_The_Clipboard;
{Your code goes here!}
EditPkg.Initialize_The_Clipboard;
If you have any questions on this, look in the NEDEMO.PAS
T_EditDemo.Save_Desktop function for how it should be done.
5) In your application's DONE destructor, be sure you deallocate the
editor buffer AFTER "TApplication.Done":
TApplication.Done;
EditPkg.Deallocate_The_Editor;
6) Check all units to ensure that "uses EDITORS" is changed to "uses
NEWEDIT".
7) If you want to use my help system, the EDITHELP.TXT file will
probably have to be revised to suit your hc???? constant naming
convention. That, or you'll have to write your own.
It's not as difficult as it sounds. I've done it with a minimum of
fuss, and several of the beta testers have done the same thing.
CREATING HELP
-------------
The file EDITHELP.TXT contains the source for the context sensitive help
system. You must compile it with the TVHC.EXE program to make it
functional. Included with NED100 is a MAKEHELP.BAT file. Simply type
MAKEHELP to generate a usable help file. Ensure that TVHC is in your
directory or path.
I've done things a bit different than normal here, so some explanation
might be in order.
All cm???? and hc???? constants are in the CMDFILE.PAS file. Seeing as
I've mixed these constants, I didn't want CMDFILE.PAS to be overwritten
by the TVHC program. What I do in the batch file is to let TVHC
generate an EDITHELP.PAS, EDITHELP.TPU, and EDITHELP.HLP file. I then
rename the EDITHELP.HLP file to NEDEMO.HLP and erase the EDITHELP.TPU
file. I keep the EDITHELP.PAS file as a handy alphabetical reference.
So, the short of it is that NEDEMO requires that the CMDFILE unit be
available and that the help file be named NEDEMO.HLP.
CODING STYLE
------------
Every one has their way of doing things, and I'm as guilty as the next
person. The only reason I bring it up is that coding style may look
very foreign to those who do it Borland's way. This is not a
justification, just an explanation!
I code the way I do so that I can quickly convert code between C,
PASCAL, and Ada.
I don't put all of my if/elses on one line. I like to see which
condition is met when I'm debugging.
I use lots of white space so things don't look as bad as they really
are<grin>.
I use 43/50 column mode and print in compressed mode, therefore my code
does tend to go beyond the right margin.
Last of all, and this is probably important to some of you, I use fully
qualified variable and procedure/function names. I HATE having to
figure out where a variable or procedure/function is. Where I work,
people are summarily shot for failing to do so!
WHEN IS A BUG NOT A BUG?
------------------------
When it's a feature, of course! I've seen several so-called bug
reports describing what the authors consider to be bugs in the
EDITORS unit, when in fact they are reporting features.
Granted, there are some bugs there, and the service these
authors provide by reporting them is invaluable.
To set the record straight, the following two items are NOT
bugs!
1) Pressing ^T will in some instances delete more than just the
word you want deleted.
Sorry, this is NOT a bug! The Editors unit defines a
particular character set. Any character not in that
character set is a "non-character". ^T works like this:
a) Delete from the cursor position all characters to the
first character not defined in our character set. That
takes care of the current word.
b) Now we need to delete all characters NOT in the
character set to the next character that IS in the
character set. That deletes the "blank space" between
words.
Step B is what most people consider the "bug" for you will
delete characters that are not in the character set between
words. It's the way the Editor was designed! You may not
like it, but that doesn't make it a bug!
This supposed "bug" is not a problem with NEWEDIT. In the
process of changing the character set to acoomodate
wordwrap, it has become a non-issue. I just wanted users to
be aware of the difference in NEWEDIT and EDITORS.
2) Selecting text and then pressing a key deletes selected
text.
This is a feature that allows you to quickly do a FIND and
then type in new text to replace old text. Yes Virginia,
you should use SEARCH/REPLACE, but there are times when this
little feature used in conjunction with FIND is invaluable.
It also allows you to mark text for quick selection and
deleting.
Several supposed "fixes" for this feature will do nothing
but clobber your FIND and/or SEARCH/REPLACE capabilities.
So what if you accidently erase the selected text -- ^Undo
it!
I have deliberately retained this feature in NEWEDIT.
Please do not report to me that FIND and/or SEARCH/REPLACE
no longer work because you tried to incorporate one of the
"bug fixes" for this alleged problem!
43/50 LINE VIDEO
----------------
Have added the capability of using 43/50 line screens if you have EGA or
better. The option can be found in the OPTIONS menu. It is
automatically disabled if the user doesn't have the capability.
Note that Load/Store remembers what video mode you were in and resets
the program to that mode when the desktop is automatically loaded.
AUTOINDENT
----------
The AutoIndent command has been changed from ^O to ^QI. I did
this for two reasons. The first is that ^O is right next to
^I, the tab key. The other is that ^QI is the WordStar
sequence for this feature. It keeps the user out of trouble,
and it makes the editor conform more to WordStar, which I
presume was Borland's original intent.
CENTERING TEXT
--------------
A line of text may be centered by using ^OC. Centering is
based on the setting of the Right_Margin. If a line is blank,
or the length of the line exceeds the Right_Margin value,
nothing will happen. Spaces at the beginning of lines are not
used when calculating the line length.
The cursor will be moved to the end of the line after it has
been centered.
CHARACTER SET
-------------
The original EDITORS unit had the following character set:
WordChars: set of Char = ['0'..'9', 'A'..'Z', '_', 'a'..'z'];
This implementation of the NEWEDIT unit has changed the
character set to be to the following:
WordChars: set of Char = ['!'..#255];
This was done to allow simpler coding for the wordwrap feature.
Note that the tab character is no longer considered a valid
character. This is described in further detail later in the
document. Also note that jumping from word to word will no
longer bypass extended ASCII characters.
COLORS
------
To be quite honest, the whole GetPalette color business is
beyond me and the TV documentation, while going into depth on
the subject, doesn't lend to clarifying the issue. So, I've
done a quick and dirty change of the whole blasted palette.
NEDEMO.PAS has a constant called New_Colors. It contains a
whole new color scheme. As a programmer, you have several
options available to you.
You can keep things like I've got them.
You can change them back to the TV defaults by deleting the
New_Colors constant and the T_EditDemo.GetPalette procedure in
its entirety.
You can open up APP.PAS and replace the CColor constant data
with the New_Colors data to make ALL your applications have
these new colors. Just make sure you delete New_Colors and
T_EditDemo.GetPalette so you don't duplicate things.
You can change New_Colors to use your own color scheme.
Play around and see what you would prefer.
The ASCII file COLORS.ASC is being distributed with NED100.ZIP
to show you how to change the color palette. It was originally
written by CIS member Steve Shafer, 71121,1771, and is available with
NED100 by his permission.
CONSTANTS
---------
I've put all of the NEWEDIT constants that support the new features in
the 200 range. I did this to allow programmers to enable/disable these
commands in any menu system they design.
CTRL-BACKSPACE
--------------
Added this feature to allow two options for deleting text from
the cursor to the left margin. You can use ^BackSpace or ^QH.
CTRL-HOME AND CTRL-END
----------------------
To add compatibility with the regular IDE editor, I have added
the ability to jump to the top and bottom of a page.
[Ctrl]-[Home] will take the cursor to the top of a page and
[Ctrl]-[End] will take the cursor to the bottom of a page.
Note that the cursor does NOT go to the first position in the
line. The actual position it ends up at is based on the current
position of the cursor on the current line when one of these
key sequences are pressed, and the length of the new line it
ends up on.
DESKTOP MENU
------------
The user should have a menu that allows them to load and store
the desktop, so I added a DESKTOP menu. I've also added the
43/50 line mode video toggle to this menu.
DOCUMENT REFORMAT
-----------------
Pressing ^QU will allow you to reformat a document from either
the current line, or the beginning of a document, to the end of
the document. A dialog box appears with radio buttons asking
you where you want to start reformatting.
You must be VERY careful when using this option. It is based
on the paragraph reformat feature. You will note in that
section that reformatting is based on the indentation of the
first line in a paragraph, and whether or not the AutoIndent
feature is toggled on.
Your screen will scroll to follow the reformat process. This
allows the user to know something is happening, instead of just
having the system lock up while text is reformatted.
END OF LINE SPACES
------------------
Spaces at the end of lines are automatically removed. This was
required to make the wordwrap and reformat feature work
properly. Spaces on blank lines are also removed. Only the
CR/LF is kept.
Spaces are NOT removed until the cursor has traveled over or
onto a line. Therefore, if you load a file created by another
ASCII editor that does not strip spaces, they will remain in
the document until you move through the document with the
cursor keys.
INDICATOR LINE
--------------
The window TIndicator line has been modified. Instead of that
stupid character that pops up to indicate the document has been
modified, an "M" now appears. Also, an "I" appears when
AutoIndent is active, and a "W" pops up when wordwrap is on.
This means I had to take some space away from the cursor stats,
but, with only 64K available, I don't think there will be a problem
unless the user is entering some weird text.
INSERT NEW LINE
---------------
Pressing ^N will insert a CR/LF pair at the current cursor
position. All characters AT the cursor and to the end of the
line will be moved down to the next line. The difference
between pressing ^N and [Enter] is that with ^N the cursor
stays at its current position and does NOT move down to the
next line. The only exception to this would be if the cursor
was at the end of a line that has its spaces removed when ^N is
pressed. In that case, the cursor goes to the new end of line.
This feature was added to allow further compatibility with the
current IDE.
JUMP TO LINE NUMBER
-------------------
Pressing ^JL will allow the user to jump to a particular line
number. A dialog box will appear that requests the user input
a line number to jump to. Valid entries range from 1 to 9999.
I believe 9999 is a high enough range. If someone thinks it
should be larger, please let me know.
The dialog box differs from the right margin and preset tab
dialogs in that the initial Line_Number value is always blank.
However, once the user inputs a value it is remembered, thereby
allowing the user to jump to the same line number after they
scroll around the text.
LOAD/STORE OPERATIONS
---------------------
The original load/store bug in EDITORS.PAS has been fixed.
In addition, new Read/Write streams have been incorporated
in TEditor.Load and TEditor.Store to allow saving of the new
variables in the TEditor object.
MEMORY
------
In the original Borland EDITORS unit, you are allowed to define how much
of an edit buffer you can set aside on the heap. This buffer size
determines how many editor windows you can have open at one time. The
default in the EDITORS unit was to take the buffer size the programmer
wanted, and to then allocate all available heap to the editors, and
leave the editors buffer size as the free space. So, you got lots of
memory so you could open up lots of editor windows.
Not everyone wants all that heap set aside for the editors. The EDITPKG
unit maintains the Borland default, but by changing two lines in the
EDITPKG.Initialize_The_Editor procedure you can set aside exactly how
much buffer space you want for the editor, and ONLY that buffer space,
leaving the rest of the heap available to your applications. Just search
for the label "HEAP" to find these two lines.
MENUS
-----
How to create menus is pretty much covered in the TurboVision
documentation, and I'm not going to cover it here. What I would
like to state is that I've provided ready-to-use code in the
NEWEDIT unit and the NEDEMO program that will allow you to
toggle your menu options on/off. All you need to do is
uncomment the code I have in place to make use of toggling your
new menu options on/off.
The T_EditDemo.Init constructor in NEDEMO contains the original
disabling code.
The TFileEditor.UpdateCommands procedure in NEWEDIT contains the
actual updating code.
WARNING!!!! You will pay a HEAVY price for each additional
SetCmdState (Command, True) line you uncomment in
procedure TfileEditor.UpdateCommands. The price is
in system response time. Uncommenting all the
lines will turn your fast 64K editor into a slow
clunky piece of junk! Of course, you don't really
need to disable/enable menu options for editor
menus you might design. My advice is to either
keep the menu minimal and uncomment only what you
really need, or leave all your editor menu options
enabled at all times.
PARAGRAPH REFORMAT
------------------
This feature is available to the user via the ^B key. It works
regardless of whether or not wordwrap is active. Reformatting
is based on the current right margin position. As with
wordwrap, reformatting is not possible if the cursor is beyond
the right margin position. An error dialog will appear.
Paragraph reformat also works with the AutoIndent feature.
However, it is important to note that the reformat process is
based on the current line the cursor happens to be sitting on
when ^B is pressed. Therefore, if you use hanging paragraphs
(a paragraph where the first line sticks out further to the
left margin than the rest of the paragraph) you need to be
careful. If the cursor is on the first line of the paragraph,
the reformatting takes place according to that line's left
margin setting. This is a feature, not a bug. Try the same
thing with MicroStar or SideKick and you'll see what I mean.
If AutoIndent is on, and the paragraph is so indented that
reformatting encounters a word that will not fit on the line
according to the left and right margin settings, an error
dialog will appear. However, any reformatting accomplished
prior to this situation will have taken effect. The cursor
should stop on the word it couldn't wrap. This should preclude
the reformatting process locking up the system because it can't
wrap a word that is too long.
The cursor will end up at the first blank line after the
paragraph when you press ^B. Therefore, you can reformat
paragraphs in quick succession.
Note that unlike some other editors, this implementation of
paragraph reformatting will retain double spaces after periods,
exclamation points, question marks, and colons. If you are in
the habit of only using one space, it's not syntactically
correct. Two spaces will be inserted instead, providing the
cursor was sitting on one of these punctuation marks when the
reformatting process was doing its thing. Otherwise, no change
will be made to your original text.
I've noticed that if the editor is almost filled to capacity
and the user tries to do a ^B on one of the last paragraphs,
the reformatting doesn't work properly. I have no idea what to
do about this, as I suspect it has something to do with buffers
and all.
PLACE MARKERS
-------------
The editor now allows the user to set place markers within the
document. ^K#, where # is a value between 1 and 0 on the
keyboard, allows the user to set up to 10 place markers. The
user can jump to a place marker by pressing ^Q#, where # is a
value between 1 and 0 on the keyboard.
Place markers are not visible, but they are there
none-the-less. They are maintained in an array called
Place_Marker, which is contained in the TEditor object.
Place markers are constantly updated as the user inserts and
deletes text. If a place marker is contained within text that
is deleted, it is set back to zero. The cursor key goes
nowhere if it encounters a place marker with a zero value as a
result of a ^Q# request. Of course, this also means you can
not set a place marker in column 1 of line 1, for it is the 0th
position in the document. Use [Ctrl]-[PgUp] instead!
PRESET TABS
-----------
A preset tab feature has been implemented, allowing the user to
define up to 74 tab stops. The ^OI keys will bring up a tab
stop dialog box. The box has a ruler across the top and an
input line beneath the ruler.
To set tabs, the user should place a character in the input
line directly beneath the ruler setting where a tab is wanted.
The input line is a normal TInputLine, therefore its behavior
follows the norm. Note that if the input line is filled with
spaces the user will not be able to enter any data. To help
alleviate this situation, the TInputLine data is stripped of
all unnecessary spaces after the last tab stop every time the
user exits the dialog box.
The data is placed in a string variable called Tab_Settings
which is contained in the TEditor object.
Tab_Settings is automatically initialized to increments of 7.
The initialization takes place in TEditor.Init.
Pressing [Esc] or the OK dialog button will keep the current
Tab_Settings.
RIGHT MARGIN
------------
The user can set the right margin of the document. This is
done by pressing the ^OR sequence. A dialog box will appear
asking the user to enter a right margin value. The current
value will be shown each time the dialog comes up. The default
value is 76. The programmer must change this to something else
in the TEditor.Init code if they want a different value. The
user has only three options; enter the value, press the OK
button, or press [Esc]. Pressing OK or [Esc] will keep the
current value. Valid entries are 10 through 255. If the user
enters a value that is not within this range, the current value
is maintained. No error message will be given!
The right margin value is contained in the TEditor object. The
variable is called Right_Margin.
SAVE FEATURES
-------------
There are several more save features than normal. I've tried
to implement the most important WordStar commands that apply to
saving the document. I've also retained Borland's current
features.
[F2] or ^KS - cmSave - Save text to current file and
resume editing.
^KF - cmSaveAs - Save text to another file.
^KD or ^KX - cmSaveDone - Save text to current file and exit
editor.
Note that where cmSaveAs used to be accessible only through a
menu option like "Save As...", it is now accessible to the
user, regardless of the programmers menu system, via the ^KF.
This applies to all the save features. They are all accessible
to the user.
SCROLL DOWN
-----------
Pressing ^Z emulates the IDE function of scrolling the screen
up while maintaining the cursor position. If the original
cursor position scrolls off the screen, the cursor scrolls down
a line. This forces the cursor to stay in the upper left
corner of the screen should the original cursor position scroll
away.
SCROLL UP
---------
Pressing ^W emulates the IDE function of scrolling the screen
down while maintaining the cursor position. If the original
cursor position scrolls off the screen, the cursor scrolls up a
line. This forces the cursor to stay in the lower left corner
of the screen should the original cursor position scroll away.
SELECT WORD
-----------
Pressing ^KT will highlight the current word the cursor is sitting on.
This function was added to maintain compatibility with the IDE.
The word is marked from the current cursor position to the next space or
end of line, whichever comes first. The marked word is put into the
clipboard without further effort on the users part. Marking works in
the normal manner, i.e., it disappears the moment you move the cursor.
Note that NOTHING will happen if you try to use this command when the
cursor is sitting on a space or the end of a line.
TABS
----
I realize that Borland allows the tab (#9) character in the
original editors package. They probably did this to allow a
maximal amount of data to fit in a small 64K buffer. However,
the current implementation of this NEWEDIT unit does not allow
tabs. I did this to make the added features a simpler exercise
in coding.
Tab works in two different ways.
When in INSERT mode, the cursor will attempt to go to the next
tab stop, happily INSERTING SPACES as it looks for that next
stopping point. If it is at the last tab stop, it stops
inserting spaces and takes a big jump to the first character of
the next line. Try to keep tab use to a minimum when the
cursor is in insert mode. You eat up valuable buffer space
real quick!
When in OVERSTRIKE mode, the cursor will attempt to go to the
next tab stop, happily skipping over characters as it looks for
that next stopping point. If it is at the last tab stop, OR
the line is too short to allow it to reach the next tab stop,
it takes a big jump to the first character of the next line.
I think you'll see that if you set your tabs right, you can
quickly indent a whole paragraph deeper than it already is.
Also, you don't come to a screeching halt. If in OVERSTRIKE
mode you can move through a document real quick.
TVFORMS DEMO AND PDEMO OBJECT
-----------------------------
So, you want wordwrap in your PDEMO object? No problem!
I'll use the GENPARTS.PAS program for the TVFORMS demo program
as an example. Find the line in the function "MakeForm" that
looks like this:
C := New (PMemo, Init (R, nil, PScrollBar(C), nil, DescrLen));
Now, add these two lines right after it:
PMemo(C)^.Word_Wrap := TRUE;
PMemo(C)^.Right_Margin := R.B.X - R.A.X;
Now you've got wordwrap! You simply type cast the Wordwrap
variable to default to TRUE and Right_Margin for where you want
wordwrap to occur, and that's all there is to it! Just
remember to do this for each and every PMemo you want wordwrap
for.
UNDO
----
^U is the normal undo feature for the NEWEDIT unit. However,
to maintain compatibility with the IDE editor, I have also
provided a ^QL option. They both do the same job.
WORDWRAP
--------
Wordwrap is toggled on/off via the ^OW sequence. When wordwrap
is on, a "W" appears on the status line. Wordwrap is fast, and
should keep up with the most fluid typist. There should be no
"jerkiness" in the wrap effect.
Wordwrap is based on the "push the line out to the right until
the cursor reaches the current right margin setting" principle.
Therefore, if you are on a line and inserting text, the text
will be pushed beyond the right margin until the cursor gets
there, at which point the text beyond the cursor is wrapped.
The right margin is considered to be the current right margin
value + 1. For example, if your right margin is set to 69,
then the cursor CAN go to column 70. Trying to exceed column
70 will cause wordwrap to occur.
Wordwrap will not work if the cursor is beyond the current
right margin setting. In this event, an error dialog box will
appear.
Wordwrap will also work with the AutoIndent mode turned on. In
this case, the cursor goes to the same first character position
on the new line as the line it was on when wrap occurred.
If you try to type a blank line of spaces to the right margin,
wordwrap will remove the spaces and insert just a CR/LF pair.
Wordwrap will also bring up an error message if you try to type
in an entire line out to the right margin without spaces.
COMMAND SUMMARY
---------------
The following list contains all the commands available in this
implementation of the Turbo Vision NEWEDIT unit.
Command TV Command Description
-------------------- ------------- ------------------------------------------------
[Ctrl]-[A] - cmWordLeft Move cursor left to previous word.
[Ctrl]-[B] - cmReformPara Reformat paragraph to current margins.
[Ctrl]-[C] - cmPageDown Page down one screen.
[Ctrl]-[D] - cmCharRight Move cursor right one character.
[Ctrl]-[E] - cmLineUp Move cursor up one line.
[Ctrl]-[F] - cmWordRight Move cursor right to next word.
[Ctrl]-[G] - cmDelChar Delete character cursor is on.
[Ctrl]-[H] - cmBackSpace Delete character to left of cursor.
[Ctrl]-[I] - cmTabKey Move right to next tab position.
[Ctrl]-[J]-[L] - cmJumpLine Jump to a line number.
* [Ctrl]-[K]-[#] - cmSetMark0-9 Set place marker (0 to 9).
[Ctrl]-[K]-[B] - cmStartSelect Begin selecting text.
[Ctrl]-[K]-[C] - cmPaste Copy text from clipboard into document.
[Ctrl]-[K]-[D] - cmSaveDone Save document and exit editor immediately.
[Ctrl]-[K]-[F] - cmSaveAs Save current document to another file.
[Ctrl]-[K]-[H] - cmHideSelect Hide selected text.
[Ctrl]-[K]-[K] - cmCopy Copy text from document into clipboard.
[Ctrl]-[K]-[S] - cmSave Save document and continue editing.
[Ctrl]-[K]-[T] - cmSelectWord Select current word cursor is on.
[Ctrl]-[K]-[Y] - cmCut Remove text from document into clipboard.
[Ctrl]-[K]-[X] - cmSaveDone Save document and exit editor immediately.
[Ctrl]-[L] - cmSearchAgain Continue searching for specified text.
[Ctrl]-[M] - cmNewLine Enter CR/LF pair.
[Ctrl]-[N] - cmInsertLine Add CR/LF pair AT cursor and keep cursor position.
[Ctrl]-[O]-[C] - cmCenterText Center text on cursor line.
[Ctrl]-[O]-[I] - cmSetTabs Set tab positions.
[Ctrl]-[O]-[R] - cmRightMargin Set right margin position of line.
[Ctrl]-[O]-[W] - cmWordWrap Toggle word wrap mode on or off.
* [Ctrl]-[Q]-[#] - cmJumpMark0-9 Move cursor to specified place marker (0 to 9).
[Ctrl]-[Q]-[A] - cmReplace Search for text and replace it.
[Ctrl]-[Q]-[C] - cmTextEnd Move cursor to end of document.
[Ctrl]-[Q]-[D] - cmLineEnd Move cursor to end of line.
[Ctrl]-[Q]-[F] - cmFind Find specified text.
[Ctrl]-[Q]-[H] - cmDelStart Delete text from cursor to start of line.
[Ctrl]-[Q]-[I] - cmIndentMode Toggle IndentMode on and off.
[Ctrl]-[Q]-[R] - cmTextStart Move cursor to beginning of document.
[Ctrl]-[Q]-[S] - cmLineStart Move cursor to beginning of line
[Ctrl]-[Q]-[U] - cmReformDoc Reformat the document text.
[Ctrl]-[Q]-[Y] - cmDelEnd Delete text from cursor to end of line.
[Ctrl]-[R] - cmPageUp Page up one screen.
[Ctrl]-[S] - cmCharLeft Move cursor left one character.
[Ctrl]-[T] - cmDelWord Delete text from current cursor to next word.
[Ctrl]-[U] - cmUndo Restore text to previous state.
[Ctrl]-[V] - cmInsMode Toggle cursor between insert and overstrike mode.
[Ctrl]-[W] - cmScrollUp Scroll screen up one line keeping cursor position.
[Ctrl]-[X] - cmLineDown Move cursor down one line.
[Ctrl]-[Y] - cmDelLine Delete line of text cursor is on.
[Ctrl]-[Z] - cmScrollDown Scroll screen down one line keeping cursor position.
[Backspace] - cmBackspace Delete character to left of cursor.
[Left Arrow] - cmCharLeft Move cursor left one character.
[Right Arrow] - cmCharRight Move cursor right one character.
[Ctrl]-[Left Arrow] - cmWordLeft Move cursor left to previous word.
[Ctrl]-[Right Arrow] - cmWordRight Move cursor right to next word.
[Home] - cmLineStart Move cursor to start of line.
[End] - cmLineEnd Move cursor to end of line.
[Ctrl]-[Home] - cmHomePage Move cursor to top of current page.
[Ctrl]-[End] - cmEndPage Move cursor to bottom of current page.
[Up Arrow] - cmLineUp Move cursor up one line.
[Down Arrow] - cmLineDown Move cursor down one line.
[PgUp] - cmPageUp Page up one screen.
[PgDn] - cmPageDown Page down one screen.
[Ctrl]-[PgUp] - cmTextStart Move cursor to beginning of document.
[Ctrl]-[PgDn] - cmTextEnd Move cursor to end of document.
[Ins] - cmInsMode Toggle cursor between insert and overstrike mode.
[Del] - cmDelChar Delete character cursor is on or selected text.
[Ctrl]-[BackSpace] - cmDelStart Delete text from cursor to start of line.
[Shift]-[Ins] - cmPaste Copy text from clipboard into document.
[Shift]-[Del] - cmCut Remove text from document into clipboard.
[Ctrl]-[Ins] - cmCopy Copy text from document into clipboard.
[Ctrl]-[Del] - cmClear Clear out and dispose of clipboard contents.
* NOTE: # implies a numeric value between 1 and 0 on the
keyboard. (i.e., 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
IDE COMMANDS NOT SUPPORTED
--------------------------
[Ctrl]-[I] - Insert a real tab character.
[Ctrl]-[K]-[I] - Indent marked block.
[Ctrl]-[K]-[P] - Print marked block
[Ctrl]-[K]-[R] - Read a file from disk and insert into document as marked block.
[Ctrl]-[K]-[U] - Unindent marked block.
[Ctrl]-[K]-[V] - Move marked block.
[Ctrl]-[K]-[W] - Write marked block to a file on disk.
[Ctrl]-[O]-[T] - Toggle between real tabs and spaced tabs.
[Ctrl]-[P]-[?] - Insert a control character (where ? is the character).
COMMANDS THAT DIFFER FROM IDE
-----------------------------
Command NewEdit IDE
------- ------- ---
[Ctrl]-[K]-[F] - Save document to a new file. ----
[Ctrl]-[O]-[I] - Set tab stops Toggle AutoIndent Mode
[Ctrl]-[Q]-[I] - Toggle AutoIndent Mode ----
[Ctrl]-[BackSpace] - Delete from cursor to left margin. ----
UNDO Menu Option - Restore the line. [Ctrl]-[Q]-[L]
HOW TO ADD CUSTOM KEY COMMANDS
------------------------------
Adding your own custom key commands, and supporting code, is an
easy matter. The only requirement is you must understand how
the different key arrays are structured. As an example, we'll
consider adding user print controls to the editor.
We start with the FirstKeys array. Note the array size in the
following code fragment:
FirstKeys : array[0..46 * 2] of Word = (46, Ord (^A), cmWordLeft,
The array has 46 elements. Each element is a word (two bytes).
That's what the 46 * 2 means. This is important, for it is how
the editor determines which key stroke, or control sequence has
been pressed.
You will note that FirstKeys consists entirely of control key
sequences, ^A, ^B, ^C, etc. To each control key a command is
tied, cmWordLeft, cmReformPara, cmPageDown, etc. Not only are
control keys found in this array, but also cursor control keys
like kbHome, kbEnd, kbUp, etc. So far, it's pretty simple.
Now, notice that three control keys have a hex word value
assigned to them, ^Q=$FF01, ^K=$FF02, ^O=$FF03, ^J=$FF04.
Just what are these word values? They are flags that let the
NEWEDIT unit know when a special control sequence has been
pressed that requires further evaluation of an additional key
to complete the command. For example, ^QI, ^KB, ^OR, or ^JL.
How does it work?
The answer is the high byte in the command tied to the keystroke,
which is $FF for these four special keys. This is a flag that
tells the ConvertEvent procedure to process the key AFTER the
control key as the actual command. How does it process it? To
answer that question, we need to dig into the other arrays
first.
Notice that after the FirstKeys array there are several other
arrays: QuickKeys, BlockKeys, FormatKeys, JumpKeys, and
finally KeyMap. The QuickKeys, BlockKeys, FormatKeys, and
JumpKeys are arrays that are tied to the ^Q, ^K, ^O, and ^J
keys. These arrays define the possible key commands that could
be tied to these keys. To illustrate this, note that FormatKey
defines all the valid keystrokes allowed for the ^O command in
FirstKeys.
The factor that ties the FormatKey array to the ^O command in
the FirstKeys array is the low byte in the $FF01 command tied
to ^O. How does this work? Very simply put, the order you
place your array into the KeyMap array is the determining
factor. Let's look at KeyMap.
KeyMap : array[0..4] of Pointer = (@FirstKeys,
@QuickKeys,
@BlockKeys,
@FormatKeys,
@JumpKeys);
Note the order of the array elements in Keymap, and the low
byte of the commands tied to the control keys we've been
discussing.
0 FirstKeys
1 QuickKeys ^Q $FF01
2 BlockKeys ^K $FF02
3 FormatKeys ^O $FF03
4 JumpKeys ^J $FF04
Do you see the relation? When ConvertEvent sees the $FF as the
high byte in the word of the event, it knows that one of these
special control key values has been pressed. It then looks for
the low byte of the word, and jumps into the KeyMap array to
determine the address of the Pointer to the proper array to get
the next key interpretation from, based on the position in the
KeyMap array corresponding to the low byte. It then goes to
that array, finds the correct key, and processes it. For
example,
^OR
1) ^O pressed, look it up in FirstKeys.
2) command is $FF03.
3) ConvertEvent finds $FF in the high byte of the word.
4) ConvertEvent knows more data follows and finds the low
byte of the command word.
5) The low byte is $03 so ConvertEvent accesses the 3rd
element of KeyMap to find the address of FormatKeys.
6) "R" is found in FormatKeys and the command tied to it,
cmRightMargin, is placed on the event queue for
HandleEvent to process.
So, how do we add new commands tied to the ^P key for printing
options?
First, define some new commands up in the constant area where
the cm??? commands are defined. Let's say we want ^PD to print
the entire document and ^PC to print the document starting at
the current cursor position. So we add new commands called
cmPrintStart and cmPrintCurrent and assign them a value not
being used by other cm??? commands. So far, so good
Second we go to the FirstKeys array and insert ^P as a new
command. We have to change the array size (46) to show we
have a new command (change 46 to 47 -- BOTH 46's to 47's). Now
tie a new command to ^P, in this case it would be $FF05. So,
we would have something like this:
CONST
...
cmPrintFirst = 550
cmPrintCurrent = 551
FirstKeys : array[0..46 * 2] of Word = (46, Ord (^A), cmWordLeft,
Ord (^B), cmReformPara,
Ord (^C), cmPageDown,
Ord (^D), cmCharRight,
Ord (^E), cmLineUp,
Ord (^F), cmWordRight,
Ord (^G), cmDelChar,
Ord (^H), cmBackSpace,
Ord (^I), cmTabKey,
Ord (^J), $FF04,,
Ord (^K), $FF02,
Ord (^L), cmSearchAgain,
Ord (^M), cmNewLine,
Ord (^N), cmInsertLine,
Ord (^O), $FF03,
Ord (^P), $FF05,
....
Now we create a new array to hold the print commands. We'll
call it PrintKeys.
PrintKeys : array[0..2 * 2] of Word = (2, Ord ('C'), cmPrintCurrent,
Ord ('D'), cmPrintStart);
Last of all we add PrintKeys to the 5th ($FF05) position in
KeyMap. Don't forget to change the array range from 4 to 5!
KeyMap : array[0..5] of Pointer = (@FirstKeys,
@QuickKeys,
@BlockKeys,
@FormatKeys,
@JumpKeys,
@PrintKeys);
Now, all you need do is add the cmPrintStart and cmPrintCurrent
commands to HandleEvent, with the appropriate procedure or
function call. Coding these procedures or functions is up to
you! Don't forget to include the declaration for the procedure
or function inside private portion the TEditor object!
Heck! Here's some code Steve Schafer posted on BPROGA that I modified to
conform to my coding style. It should get you started.
uses ... Printer;
procedure TEditor.Print_Document;
VAR
P: Word; { Position of CurPtr. }
begin
for P := 0 to BufLen do { Print from beginning to end. }
Write (Lst, BufChar (P)); { Print the character. }
end { TEditor.Print_Document };